/*********************************************************************************
 *      Copyright:  (C) 2023 iot<iot@email.com>
 *                  All rights reserved.
 *
 *       Filename:  logger.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(03/10/23)
 *         Author:  iot <iot@email.com>
 *      ChangeLog:  1, Release initial version on "03/10/23 09:31:26"
 *                 
 ********************************************************************************/

#include <stdio.h>
#include <error.h>
#include <errno.h>
#include <time.h>
#include <stdarg.h>
#include <string.h>
#include "logger.h"

extern const char *__progname;
#define PROGRAM_NAME __progname

typedef struct logger_s
{
	FILE	*fp;
	int		loglevel;
	int		use_stdout;
} logger_t;

static struct logger_s g_logger;

static const char *LOG_LEVELS[] = 
{
	LOG_STRING_CRITICAL,
	LOG_STRING_ERROR,
	LOG_STRING_WARNING,
	LOG_STRING_INFO,
	LOG_STRING_DEBUG
};

int logger_init(char *filename,int loglevel)
{
	logger_term();

	g_logger.loglevel = loglevel>LOG_LEVEL_MAX ? LOG_LEVEL_MAX : loglevel;	
	if( !filename || !strcasecmp(filename,"stdout"))
	{
		g_logger.use_stdout = 1;
		g_logger.fp = stderr;
	}
	else
	{
		g_logger.use_stdout = 0;
		g_logger.fp = fopen(filename,"a");  //a write after it as an append
		if( !g_logger.fp )
		{
			fprintf(stderr,"failed to open file '%s':%s\n",filename,strerror(errno));
			return -1;
		}
	}
	return 0;
}

void logger_term(void)
{
	if( !g_logger.fp )
	{
		return;
	}

	if( !g_logger.use_stdout )
	{
		fclose(g_logger.fp);
	}
	
	g_logger.use_stdout = 0;
	g_logger.fp = NULL;

	return;
}

void log_generic(const int level,const char *format,va_list args)
{
	char		message[512];
	struct tm	*current_tm;
	time_t		time_now;

	vsprintf(message,format,args);

	time(&time_now);
	current_tm = localtime(&time_now);

	int res = fprintf(g_logger.fp
							,"%s : %02i:%02i:%02i [%s] %s\n"
							,PROGRAM_NAME
							,current_tm->tm_hour
							,current_tm->tm_min
							,current_tm->tm_sec
							,LOG_LEVELS[level]
							,message );

	fflush(g_logger.fp);
}

void log_critical(char *format,...)  //variable-parameter macro
{
	va_list args;
	va_start(args,format);
	log_generic(LOG_LEVEL_CRITICAL,format,args);
	va_end(args);
}

void log_error(char *format,...)  //variable-parameter macro
{
	va_list args;
	va_start(args,format);
	log_generic(LOG_LEVEL_ERROR,format,args);
	va_end(args);
}

void log_warning(char *format,...)
{
	if( g_logger.loglevel < LOG_LEVEL_WARNING )
	{
		return;
	}

	va_list args;
	va_start(args,format);
	log_generic(LOG_LEVEL_WARNING,format,args);
	va_end(args);
}

void log_info(char *format,...)
{
	if( g_logger.loglevel < LOG_LEVEL_INFO )
	{
		return;
	}

	va_list args;
	va_start(args,format);
	log_generic(LOG_LEVEL_INFO,format,args);
	va_end(args);
}
void log_debug(char *format,...)
{
	if( g_logger.loglevel < LOG_LEVEL_DEBUG )
	{
		return;
	}

	va_list args;
	va_start(args,format);
	log_generic(LOG_LEVEL_DEBUG,format,args);
	va_end(args);
}


